package com.hello.sky.aspect;


import com.hello.sky.annotation.AutoFill;
import com.hello.sky.constant.JwtClaimsConstant;
import com.hello.sky.enmu.OperationType;
import com.hello.sky.util.JwtUtil;
import io.jsonwebtoken.Claims;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;

@Slf4j
@Aspect
@Component
public class AutoFillAspect {

    @Autowired
    private HttpServletRequest request;

    @Before("autoFillPoint()")
    public void autoFill(JoinPoint joinPoint) throws NoSuchMethodException {
        //拿到该类对象的该方法上的注解参数
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        // 获取方法参数类型
        Class<?>[] parameterTypes = new Class[joinPoint.getArgs().length];
        for (int i = 0; i < args.length; i++) {
            if (args[i] != null) {
                parameterTypes[i] = args[i].getClass();
            } else {
                // 如果参数为null，可以考虑使用Object.class作为占位符或者其他处理方式
                parameterTypes[i] = Object.class; // 或者其他处理方式
            }
        }
        // 获取目标方法的Method对象
        Method[] methods = joinPoint.getSignature().getDeclaringType().getMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName) && Arrays.equals(method.getParameterTypes(), parameterTypes)) {
                // 使用method对象进行需要的操作
                AutoFill autoFill = method.getAnnotation(AutoFill.class);
                if (autoFill.value() == OperationType.INSERT) {
                    String jwt;
                    Long createUser;
                    jwt = request.getHeader("token");
                    //员工和用户请求头记录jwt的key不一样，因此这里要做判断
                    if (jwt != null){
                        //员工
                        Claims claims = JwtUtil.parseJwtThenReturnId(jwt);
                        createUser = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());

                    }else {
                        //用户
                        jwt = request.getHeader("authentication");
                        Claims claims = JwtUtil.parseJwtThenReturnId(jwt);
                        createUser = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
                    }


                    LocalDateTime createTime = LocalDateTime.now();
                    for (Object arg : args) {
                        //遍历每个参数对象，如果有设置时间和更新人id之类的方法就进行赋值
                        //todo 处理参数为集合情况下的批量插入
                        Arrays.stream(arg.getClass().getMethods()).forEach(me -> {
                            try {
                                if (me.getName().equals("setCreateTime")) me.invoke(arg, createTime);
                                if (me.getName().equals("setCreateUser")) me.invoke(arg, createUser);
                                if (me.getName().equals("setUpdateTime")) me.invoke(arg, createTime);
                                if (me.getName().equals("setUpdateUser")) me.invoke(arg, createUser);
                            } catch (Exception e) {
                                log.error("插入公共字段失败{}", e.getMessage());
                            }
                        });
                    }
                }

                if (autoFill.value() == OperationType.UPDATE) {
                    String jwt;
                    Long updateUser;
                    jwt = request.getHeader("token");
                    //员工和用户请求头记录jwt的key不一样，因此这里要做判断
                    if (jwt != null){
                        //员工
                        Claims claims = JwtUtil.parseJwtThenReturnId(jwt);
                        updateUser = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());

                    }else {
                        //用户
                        jwt = request.getHeader("authentication");
                        Claims claims = JwtUtil.parseJwtThenReturnId(jwt);
                        updateUser = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
                    }
                    LocalDateTime updateTime = LocalDateTime.now();
                    for (Object arg : args) {
                        //遍历每个参数对象，如果有设置时间和更新人id之类的方法就进行赋值
                        Arrays.stream(arg.getClass().getMethods()).forEach(me -> {
                            try {
                                if (me.getName().equals("setUpdateTime")) me.invoke(arg, updateTime);
                                if (me.getName().equals("setUpdateUser")) me.invoke(arg, updateUser);
                            } catch (Exception e) {
                                log.error("插入公共字段失败{}", e.getMessage());
                            }
                        });
                    }
                }
            }
        }


    }

    @Pointcut("execution(* com.hello.sky.mapper.*.*(..)) && @annotation(com.hello.sky.annotation.AutoFill)")
    public void autoFillPoint() {
    }
}
